package com.arpa.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.arpa.core.web.Result;
import com.arpa.ntocc.common.common.cache.PartyCache;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.wms.cache.GoodsCache;
import com.arpa.wms.cache.GoodsUnitConversionCache;
import com.arpa.wms.cache.SupplierCache;
import com.arpa.wms.cache.UnitCache;
import com.arpa.wms.domain.dto.ReceiveItemDTO;
import com.arpa.wms.domain.entity.*;
import com.arpa.wms.domain.enums.ReceiveRegisterStatusEnum;
import com.arpa.wms.domain.vo.BatchRuleVO;
import com.arpa.wms.domain.vo.ReceiveItemVO;
import com.arpa.wms.domain.vo.ReceiveItemWithRegisterVO;
import com.arpa.wms.mapper.ReceiveItemMapper;
import com.arpa.wms.mapper.ReceiveMapper;
import com.arpa.wms.service.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

import static com.arpa.wms.domain.consts.NumConst.NUM_ONE;
import static com.arpa.wms.domain.consts.NumConst.NUM_ZERO;

/**
 * <p>
 * 收货明细 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-08-04
 */
@Service
public class ReceiveItemServiceImpl extends ServiceImpl<ReceiveItemMapper, ReceiveItem> implements IReceiveItemService {


    @Autowired
    private IBatchRuleService batchRuleService;

    @Autowired
    private IGoodsUnitService iGoodsUnitService;

    @Autowired
    private UnitCache unitCache;

    @Resource
    private ReceiveMapper receiveMapper;

    @Autowired
    private PartyCache partyCache;

    @Autowired
    private SupplierCache supplierCache;
    @Autowired
    private GoodsUnitConversionCache goodsUnitConversionCache;
    @Autowired
    @Lazy
    private IInventoryStatusService inventoryStatusService;

    @Autowired
    private IGoodsPnService goodsPnService;

    @Autowired
    private GoodsCache goodsCache;
    /**
     * 保存
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public boolean save(ReceiveItem entity) {
        if(StringUtils.isBlank(entity.getCode())){
            entity.setCode(IdUtil.simpleUUID());
        }
        if(StringUtils.isBlank(entity.getCreatedBy())){
            entity.setCreatedBy(UserUtil.getCode());
        }
        return super.save(entity);
    }

    /**
     * 根据code更新实体
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public int updateByCode(ReceiveItem entity) {
        if(StringUtils.isBlank(entity.getModifiedBy())){
            entity.setModifiedBy(UserUtil.getCode());
        }
        return baseMapper.update(entity,new QueryWrapper<ReceiveItem>().lambda().eq(ReceiveItem::getCode,entity.getCode()));
    }

    /**
     * 查询列表
     * @param receiveItemDTO
     * @return
     */
    @Override
    public List<ReceiveItemVO> queryList(ReceiveItemDTO receiveItemDTO){
        receiveItemDTO.setGroupCode(UserUtil.getBranchCode());
        //排序字段名需要驼峰转数据库下划线类型字段名
        if(StringUtils.isNotEmpty(receiveItemDTO.getSortField())){
            receiveItemDTO.setSortField(CommonUtil.camel2Underline(receiveItemDTO.getSortField()));
        }
        List<ReceiveItemVO> receiveItemVOList = baseMapper.queryList(receiveItemDTO);
        return receiveItemVOList;
    }

    @Override
    public List<ReceiveItemVO> getReceiveItemByGoods(List<String> list) {
        return baseMapper.getReceiveItemByGoods(list);
    }

    /**
     * 查询合计,包含总数
     * @param receiveItemDTO
     * @return
     */
    @Override
    public ReceiveItemVO queryListSum(ReceiveItemDTO receiveItemDTO){
        ReceiveItemVO receiveItemVO = baseMapper.queryListSum(receiveItemDTO);
        return receiveItemVO;
    }




    /**
     * 返回一个itemVO
     *
     * @param code code
     * @return
     */
    @Override
    public ReceiveItemVO getOneByCode(String code) {
        ReceiveItem receiveItem = getOne(new QueryWrapper<ReceiveItem>().lambda().eq(ReceiveItem::getCode, code));
        if(receiveItem==null){
            throw new ServiceException("收货明细："+code+"不存在！");
        }

        ReceiveItemVO receiveItemVO = new ReceiveItemVO();
        BeanUtil.copyProperties(receiveItem, receiveItemVO);
        assembleReceiveItemVO(receiveItemVO);
        return receiveItemVO;
    }

    /**
     * 关联主表查询收货单信息
     * @param receiveItemDTO
     * @return
     */
    @Override
    public List<ReceiveItemVO> queryWithReceiveList(ReceiveItemDTO receiveItemDTO) {
        return baseMapper.queryWithReceiveList(receiveItemDTO);
    }

    @Override
    public List<ReceiveItem> queryAllListByReceiveCode(String receiveCode,String groupCode) {
        List<ReceiveItem> items = baseMapper.selectList(new QueryWrapper<ReceiveItem>().lambda()
                .eq(ReceiveItem::getReceiveCode, receiveCode)
                .eq(ReceiveItem::getGroupCode,groupCode));
        return items;
    }

    @Override
    public List<ReceiveItemVO> queryReturnList(ReceiveItemDTO receiveItemDTO) {
        receiveItemDTO.setGroupCode(UserUtil.getBranchCode());
        return this.baseMapper.queryReturnList(receiveItemDTO);
    }

    @Override
    public Result register(ReceiveItemDTO receiveItemDTO) {

        if(StrUtil.isBlank(receiveItemDTO.getReceiveCode())){
            throw new ServiceException("收货单不存在！");
        }
        Receive receive = receiveMapper.selectOne(new LambdaQueryWrapper<Receive>().select(Receive::getShipmentCode)
                .eq(Receive::getCode,receiveItemDTO.getReceiveCode())
                .eq(Receive::getGroupCode,UserUtil.getBranchCode()));
        if(receive==null||StrUtil.isBlank(receive.getShipmentCode())){
            throw new ServiceException("收货单不存在！");
        }
        if (StrUtil.isNotBlank(receiveItemDTO.getGoodsBarCode())) {
            String goodsCode = goodsPnService.getGoodsCode(receive.getShipmentCode(),receiveItemDTO.getGoodsBarCode());
            if(StrUtil.isNotBlank(goodsCode)){
                receiveItemDTO.setGoodsBarCode("");
                receiveItemDTO.setGoodsCode(goodsCode);
            }
        }
        List<ReceiveItemVO> receiveItemVOList = queryList(receiveItemDTO);
        if(IterUtil.isEmpty(receiveItemVOList)) {
            throw new ServiceException("收货明细：条码为" + receiveItemDTO.getGoodsBarCode() + "的商品不存在！");
        }
        // 如果有多条
        if(receiveItemVOList.size() > NUM_ONE) {
            if(StrUtil.isBlank(receiveItemDTO.getCode())) {
                return Result.ok().data(receiveItemVOList);
            }

            List<ReceiveItemVO> collect = receiveItemVOList.stream().filter(item -> item.getCode().equals(receiveItemDTO.getCode())).collect(Collectors.toList());
            assembleReceiveItemVO(collect.get(NUM_ZERO));

            return Result.ok().data(collect);
        }

        assembleReceiveItemVO(receiveItemVOList.get(NUM_ZERO));
        return Result.ok().data(receiveItemVOList);
    }

    /**
     * @param receiveCode :
     * @description 获取收货单可退明细
     * @author xuyang
     * @date 2020/12/15 18:37
     **/
    @Override
    public List<ReceiveItemVO> findReceiveRefundItems(String receiveCode) {
        // 根据订单表，查询订单明细
        List<ReceiveItem> receiveItems = this.list(new QueryWrapper<ReceiveItem>().lambda().eq(ReceiveItem::getReceiveCode, receiveCode).eq(ReceiveItem::getGroupCode,UserUtil.getBranchCode()));
        // 过滤掉可用数量为0的
        receiveItems = receiveItems.stream().filter(e ->
                e.getInboundQuantity().compareTo(e.getRefundQuantity()) > 0
        ).collect(Collectors.toList());

        List<ReceiveItemVO> receiveItemVOs = receiveItems.stream().map(e ->{
            // 清空code，这个是入货单明细的code，如果不清空，会与前端收货明细code混淆;用receiveItemCode代替
            ReceiveItemVO vo = new ReceiveItemVO();
            BeanUtil.copyProperties(e, vo);
            vo.setCanReturnQuantity(e.getInboundQuantity().subtract(e.getRefundQuantity()));
            vo.setReceiveItemCode(e.getCode());
            vo.setCode(StrUtil.EMPTY);
            vo.setGoodsUnitName(unitCache.translate(e.getGoodsUnit()));
            return vo;
        }).collect(Collectors.toList());

        return receiveItemVOs;
    }

    /**
     * 统计收货确认单上架数量，更新指定收货明细单的上架数量
     *
     * @param receiveItemCode
     */
    @Override
    public void refreshPutawayQuantity(String receiveItemCode) {
        this.baseMapper.refreshPutawayQuantity(receiveItemCode, ReceiveRegisterStatusEnum.FINISH_RECEIVE.getValue(),UserUtil.getBranchCode());
    }

    /**
     * 统计收货确认单上架数量，更新指定收货明细单的上架和入库数量
     *
     * @param receiveItemCode
     */
    @Override
    public void refreshPutawayAndInboundQuantity(String receiveItemCode) {
        this.baseMapper.refreshPutawayAndInboundQuantity(receiveItemCode, ReceiveRegisterStatusEnum.FINISH_RECEIVE.getValue(),UserUtil.getBranchCode());
    }

    /**
     * 查询明细、收货登记信息， 带分页逻辑
     *
     * @param receiveItemDTO
     * @return
     */
    @Override
    public List<ReceiveItemWithRegisterVO> queryItemWithRegisterListWithPage(ReceiveItemDTO receiveItemDTO) {
        receiveItemDTO.setGroupCode(UserUtil.getBranchCode());
        return this.baseMapper.queryItemWithRegisterListWithPage(receiveItemDTO);
    }

    @Override
    public List<ReceiveItemWithRegisterVO> queryItemWithRegisterList(ReceiveItemDTO receiveItemDTO) {
        return this.baseMapper.queryItemWithRegisterList(receiveItemDTO);
    }

    @Override
    public List<ReceiveItemWithRegisterVO> queryItemWithRegisterListByPaging(ReceiveItemDTO receiveItemDTO) {
        return this.baseMapper.queryItemWithRegisterListByPaging(receiveItemDTO);
    }

    /**
     * 组装收货单明细VO
     * @param receiveItemVO
     */
    private void assembleReceiveItemVO(ReceiveItemVO receiveItemVO) {
        String groupCode = receiveItemVO.getGroupCode();
        BatchRuleVO batchRuleVO = batchRuleService.findVoByreceiveItemCode(receiveItemVO.getCode());
        if(ObjectUtil.isNotNull(batchRuleVO)) {
            receiveItemVO.setBatchRuleVO(batchRuleVO);
            //批次规则选中生产日期时，更新商品的保质期
            if (1 == batchRuleVO.getGmtManufacture()) {
                updateExpirationQuantity(receiveItemVO.getCode(),receiveItemVO.getGoodsCode());
                //更新receiveItemVO中的保质期时间
                ReceiveItem receiveItem = this.getOne(new LambdaQueryWrapper<ReceiveItem>().eq(ReceiveItem::getCode, receiveItemVO.getCode()));
                receiveItemVO.setExpirationQuantity(receiveItem.getExpirationQuantity());
            }
        }

        // 翻译
        receiveItemVO.setGoodsUnitName(unitCache.translate(receiveItemVO.getGoodsUnit()));
        // 获取主单上的供应商名称
        Receive receive = receiveMapper.getOneByCode(receiveItemVO.getReceiveCode(),groupCode);
        if(StrUtil.isNotBlank(receive.getSupplierCode())) {
            receiveItemVO.setSupplier(supplierCache.translate(receive.getSupplierCode()));
        }
        receiveItemVO.setShipmentCode(receive.getShipmentCode());

        // 获取商品单位
        List<GoodsUnitConversion> goodsUnitConversions = goodsUnitConversionCache.get(receiveItemVO.getGoodsCode());
        receiveItemVO.setGoodsUnitConversionList(goodsUnitConversions);
        // 获取库存状态
        List<InventoryStatus> inventoryStatusList = inventoryStatusService.list(new QueryWrapper<InventoryStatus>().lambda().eq(InventoryStatus::getShipmentCode, receive.getShipmentCode()).eq(InventoryStatus::getGroupCode,groupCode));
        receiveItemVO.setInventoryStatusList(inventoryStatusList);
    }

    /**
     * 更新收货明细里的商品保质期
     * @param code
     * @param goodsCode
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean updateExpirationQuantity(String code, String goodsCode){
        Goods goods = goodsCache.getObj(goodsCode);
        if (null == goods) {
            log.error("通过商品code【" + goodsCode + "】未查到商品信息");
            return false;
        }
        BigDecimal expirationQuantity = goods.getQuality();

        return this.update(new LambdaUpdateWrapper<ReceiveItem>()
                .eq(ReceiveItem::getCode, code)
                .eq(ReceiveItem::getGoodsCode,goodsCode)
                .set(ReceiveItem::getExpirationQuantity, expirationQuantity)
        );
    }


}
